/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// TGUI - Texus's Graphical User Interface
// Copyright (C) 2012 Bruno Van de Velde (VDV_B@hotmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
//    you must not claim that you wrote the original software.
//    If you use this software in a product, an acknowledgment
//    in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
//    and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


#ifndef _TGUI_VECTORS_INCLUDED_
#define _TGUI_VECTORS_INCLUDED_

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace tgui
{
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    template <typename T>
    struct TGUI_API Vector4
    {
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Default constructor
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        Vector4() :
        x1(0),
        x2(0),
        x3(0),
        x4(0)
        {
        }


        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Construct the vector from its coordinates
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        Vector4(T X1, T X2, T X3, T X4) :
        x1(X1),
        x2(X2),
        x3(X3),
        x4(X4)
        {
        }


        ////////////////////////////////////////////////////////////
        /// Construct the vector from another type of vector
        ////////////////////////////////////////////////////////////
        template <typename U>
        explicit Vector4(const Vector4<U>& vector) :
        x1(static_cast<T>(vector.x1)),
        x2(static_cast<T>(vector.x2)),
        x3(static_cast<T>(vector.x3)),
        x4(static_cast<T>(vector.x4))
        {
        }


        /// Member data
        T x1;

        /// Member data
        T x2;

        /// Member data
        T x3;

        /// Member data
        T x4;
    };


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Overload of unary operator -
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    template <typename T>
    inline Vector4<T> operator -(const Vector4<T>& right)
    {
        return Vector4<T>(-right.x1, -right.x2, -right.x3, -right.x4);
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Overload of binary operator +=
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    template <typename T>
    inline Vector4<T>& operator +=(Vector4<T>& left, const Vector4<T>& right)
    {
        left.x1 += right.x1;
        left.x2 += right.x2;
        left.x3 += right.x3;
        left.x4 += right.x4;

        return left;
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Overload of binary operator -=
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    template <typename T>
    inline Vector4<T>& operator -=(Vector4<T>& left, const Vector4<T>& right)
    {
        left.x1 -= right.x1;
        left.x2 -= right.x2;
        left.x3 -= right.x3;
        left.x4 -= right.x4;

        return left;
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Overload of binary operator +
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    template <typename T>
    inline Vector4<T> operator +(const Vector4<T>& left, const Vector4<T>& right)
    {
        return Vector4<T>(left.x1 + right.x1, left.x2 + right.x2, left.x3 + right.x3, left.x4 + right.x4);
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Overload of binary operator -
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    template <typename T>
    inline Vector4<T> operator -(const Vector4<T>& left, const Vector4<T>& right)
    {
        return Vector4<T>(left.x1 - right.x1, left.x2 - right.x2, left.x3 - right.x3, left.x4 - right.x4);
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Overload of binary operator *
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    template <typename T>
    inline Vector4<T> operator *(const Vector4<T>& left, T right)
    {
        return Vector4<T>(left.x1 * right, left.x2 * right, left.x3 * right, left.x4 * right);
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Overload of binary operator *
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    template <typename T>
    inline Vector4<T> operator *(T left, const Vector4<T>& right)
    {
        return Vector4<T>(right.x1 * left, right.x1 * left, right.x3 * left, right.x4 * left);
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Overload of binary operator *=
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    template <typename T>
    inline Vector4<T>& operator *=(Vector4<T>& left, T right)
    {
        left.x1 *= right;
        left.x2 *= right;
        left.x3 *= right;
        left.x4 *= right;

        return left;
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Overload of binary operator /
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    template <typename T>
    inline Vector4<T> operator /(const Vector4<T>& left, T right)
    {
        return Vector4<T>(left.x1 / right, left.x2 / right, left.x3 / right, left.x4 / right);
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Overload of binary operator /=
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    template <typename T>
    inline Vector4<T>& operator /=(Vector4<T>& left, T right)
    {
        left.x1 /= right;
        left.x2 /= right;
        left.x3 /= right;
        left.x4 /= right;

        return left;
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Overload of binary operator ==
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    template <typename T>
    inline bool operator ==(const Vector4<T>& left, const Vector4<T>& right)
    {
        return (left.x1 == right.x1) && (left.x2 == right.x2) && (left.x3 == right.x3) && (left.x4 == right.x4);
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Overload of binary operator !=
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    template <typename T>
    inline bool operator !=(const Vector4<T>& left, const Vector4<T>& right)
    {
        return (left.x1 != right.x1) || (left.x2 != right.x2) || (left.x3 != right.x3) || (left.x4 != right.x4);
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    typedef sf::Vector2<float>        Vector2f;
    typedef sf::Vector2<int>          Vector2i;
    typedef sf::Vector2<unsigned int> Vector2u;

    typedef sf::Vector3<float>        Vector3f;
    typedef sf::Vector3<int>          Vector3i;
    typedef sf::Vector3<unsigned int> Vector3u;

    typedef Vector4<float>            Vector4f;
    typedef Vector4<int>              Vector4i;
    typedef Vector4<unsigned int>     Vector4u;

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //_TGUI_VECTORS_INCLUDED_
